#define USBHUB_CLASS_CODE 9
+static int usbback_is_loaded(libxl__gc *gc)
+{
+ int r;
+ struct stat st;
+
+ r = lstat(SYSFS_USBBACK_DRIVER, &st);
+
+ if (r == 0)
+ return 1;
+ if (r < 0 && errno == ENOENT)
+ return 0;
+ LOGE(ERROR, "Accessing %s", SYSFS_USBBACK_DRIVER);
+ return ERROR_FAIL;
+}
+
static int libxl__device_usbctrl_setdefault(libxl__gc *gc, uint32_t domid,
libxl_device_usbctrl *usbctrl)
{
if (usbctrl->type == LIBXL_USBCTRL_TYPE_AUTO) {
if (domtype == LIBXL_DOMAIN_TYPE_PV) {
- usbctrl->type = LIBXL_USBCTRL_TYPE_PV;
+ rc = usbback_is_loaded(gc);
+ if (rc < 0)
+ goto out;
+ usbctrl->type = rc ? LIBXL_USBCTRL_TYPE_PV
+ : LIBXL_USBCTRL_TYPE_QUSB;
} else if (domtype == LIBXL_DOMAIN_TYPE_HVM) {
/* FIXME: See if we can detect PV frontend */
usbctrl->type = LIBXL_USBCTRL_TYPE_DEVICEMODEL;
rc = libxl__resolve_domid(gc, usbctrl->backend_domname,
&usbctrl->backend_domid);
+
+out:
return rc;
}
{
device->backend_devid = usbctrl->devid;
device->backend_domid = usbctrl->backend_domid;
- device->backend_kind = LIBXL__DEVICE_KIND_VUSB;
+ device->backend_kind = (usbctrl->type == LIBXL_USBCTRL_TYPE_PV)
+ ? LIBXL__DEVICE_KIND_VUSB
+ : LIBXL__DEVICE_KIND_QUSB;
device->devid = usbctrl->devid;
device->domid = domid;
device->kind = LIBXL__DEVICE_KIND_VUSB;
/* Add usbctrl information to xenstore.
*
- * Adding a usb controller will add a new 'vusb' device in xenstore, and
- * add corresponding frontend, backend information to it. According to
- * "update_json", decide wether to update json config file.
+ * Adding a usb controller will add a new 'qusb' or 'vusb' device in xenstore,
+ * and add corresponding frontend, backend information to it. According to
+ * "update_json", decide whether to update json config file.
*/
static int libxl__device_usbctrl_add_xenstore(libxl__gc *gc, uint32_t domid,
libxl_device_usbctrl *usbctrl,
DEVICE_ADD(usbctrl, usbctrls, domid, &usbctrl_saved,
COMPARE_USBCTRL, &d_config);
+
+ if (usbctrl->type == LIBXL_USBCTRL_TYPE_QUSB) {
+ if (!libxl__query_qemu_backend(gc, domid, usbctrl->backend_domid,
+ "qusb", false)) {
+ LOG(ERROR, "backend type not supported by device model");
+ rc = ERROR_FAIL;
+ goto out;
+ }
+ }
}
for (;;) {
return rc;
}
+static char *pvusb_get_device_type(libxl_usbctrl_type type)
+{
+ switch (type) {
+ case LIBXL_USBCTRL_TYPE_PV:
+ return "vusb";
+ case LIBXL_USBCTRL_TYPE_QUSB:
+ return "qusb";
+ default:
+ return NULL;
+ }
+}
+
/* AO operation to add a usb controller.
*
* Generally, it does:
}
}
- if (usbctrl->type != LIBXL_USBCTRL_TYPE_PV) {
+ if (usbctrl->type != LIBXL_USBCTRL_TYPE_PV &&
+ usbctrl->type != LIBXL_USBCTRL_TYPE_QUSB) {
LOG(ERROR, "Unsupported USB controller type");
rc = ERROR_FAIL;
goto out;
rc = libxl_device_usbctrl_getinfo(CTX, domid, &usbctrl, &usbctrlinfo);
if (rc) goto out;
- if (usbctrlinfo.type != LIBXL_USBCTRL_TYPE_PV) {
+ if (usbctrlinfo.type != LIBXL_USBCTRL_TYPE_PV &&
+ usbctrlinfo.type != LIBXL_USBCTRL_TYPE_QUSB) {
LOG(ERROR, "Unsupported USB controller type");
rc = ERROR_FAIL;
goto out;
const char *be_path;
int r;
uint32_t be_domid, fe_domid;
+ char be_type[16];
r = libxl__xs_read_checked(gc, XBT_NULL, GCSPRINTF("%s/backend", fe_path),
&be_path);
/* Check to see that it has the proper form, and that fe_domid ==
* target domid */
- r = sscanf(be_path, "/local/domain/%d/backend/vusb/%d",
- &be_domid, &fe_domid);
+ r = sscanf(be_path, "/local/domain/%d/backend/%15[^/]/%d",
+ &be_domid, be_type, &fe_domid);
- if (r != 2 || fe_domid != tgt_domid) {
+ if (r != 3 || fe_domid != tgt_domid) {
LOG(ERROR, "Malformed backend, refusing to use");
return NULL;
}
for (j = 0; j < usbctrls[i].ports; j++) {
const char *path, *tmp;
- path = GCSPRINTF("%s/backend/vusb/%d/%d/port/%d",
+ path = GCSPRINTF("%s/backend/%s/%d/%d/port/%d",
libxl__xs_get_dompath(gc, LIBXL_TOOLSTACK_DOMID),
+ pvusb_get_device_type(usbctrls[i].type),
domid, usbctrls[i].devid, j + 1);
rc = libxl__xs_read_checked(gc, XBT_NULL, path, &tmp);
if (rc) goto out;
/* Add usb information to xenstore
*
- * Adding a usb device won't create new 'vusb' device, but only write
+ * Adding a usb device won't create new 'qusb'/'vusb' device, but only write
* the device busid to the controller:port in xenstore.
*/
static int libxl__device_usbdev_add_xenstore(libxl__gc *gc, uint32_t domid,
libxl_device_usbdev *usbdev,
+ libxl_usbctrl_type type,
bool update_json)
{
char *be_path, *busid;
if (rc) goto out;
}
- be_path = GCSPRINTF("%s/backend/vusb/%d/%d/port/%d",
+ be_path = GCSPRINTF("%s/backend/%s/%d/%d/port/%d",
libxl__xs_get_dompath(gc, LIBXL_TOOLSTACK_DOMID),
+ pvusb_get_device_type(type),
domid, usbdev->ctrl, usbdev->port);
LOG(DEBUG, "Adding usb device %s to xenstore: controller %d, port %d",
}
static int libxl__device_usbdev_remove_xenstore(libxl__gc *gc, uint32_t domid,
- libxl_device_usbdev *usbdev)
+ libxl_device_usbdev *usbdev,
+ libxl_usbctrl_type type)
{
char *be_path;
- be_path = GCSPRINTF("%s/backend/vusb/%d/%d/port/%d",
+ be_path = GCSPRINTF("%s/backend/%s/%d/%d/port/%d",
libxl__xs_get_dompath(gc, LIBXL_TOOLSTACK_DOMID),
+ pvusb_get_device_type(type),
domid, usbdev->ctrl, usbdev->port);
LOG(DEBUG, "Removing usb device from xenstore: controller %d, port %d",
}
static char *usbdev_busid_from_ctrlport(libxl__gc *gc, uint32_t domid,
- libxl_device_usbdev *usbdev)
+ libxl_device_usbdev *usbdev,
+ libxl_usbctrl_type type)
{
return libxl__xs_read(gc, XBT_NULL,
- GCSPRINTF("%s/backend/vusb/%d/%d/port/%d",
+ GCSPRINTF("%s/backend/%s/%d/%d/port/%d",
libxl__xs_get_dompath(gc, LIBXL_TOOLSTACK_DOMID),
- domid, usbdev->ctrl, usbdev->port));
+ pvusb_get_device_type(type),
+ domid, usbdev->ctrl, usbdev->port));
}
/* get original driver path of usb interface, stored in @drvpath */
goto out;
}
- rc = libxl__device_usbdev_add_xenstore(gc, domid, usbdev, update_json);
+ rc = libxl__device_usbdev_add_xenstore(gc, domid, usbdev,
+ LIBXL_USBCTRL_TYPE_PV,
+ update_json);
if (rc) goto out;
rc = usbback_dev_assign(gc, busid);
if (rc) {
- libxl__device_usbdev_remove_xenstore(gc, domid, usbdev);
+ libxl__device_usbdev_remove_xenstore(gc, domid, usbdev,
+ LIBXL_USBCTRL_TYPE_PV);
goto out;
}
+ break;
+ case LIBXL_USBCTRL_TYPE_QUSB:
+ rc = libxl__device_usbdev_add_xenstore(gc, domid, usbdev,
+ LIBXL_USBCTRL_TYPE_QUSB,
+ update_json);
+ if (rc) goto out;
+
break;
case LIBXL_USBCTRL_TYPE_DEVICEMODEL:
default:
switch (usbctrlinfo.type) {
case LIBXL_USBCTRL_TYPE_PV:
- busid = usbdev_busid_from_ctrlport(gc, domid, usbdev);
+ busid = usbdev_busid_from_ctrlport(gc, domid, usbdev, usbctrlinfo.type);
if (!busid) {
rc = ERROR_FAIL;
goto out;
goto out;
}
- rc = libxl__device_usbdev_remove_xenstore(gc, domid, usbdev);
+ rc = libxl__device_usbdev_remove_xenstore(gc, domid, usbdev,
+ LIBXL_USBCTRL_TYPE_PV);
if (rc) {
LOG(ERROR, "Error removing device from guest."
" Try running usbdev-detach again.");
goto out;
}
+ break;
+ case LIBXL_USBCTRL_TYPE_QUSB:
+ rc = libxl__device_usbdev_remove_xenstore(gc, domid, usbdev,
+ LIBXL_USBCTRL_TYPE_QUSB);
+ if (rc) goto out;
+
break;
case LIBXL_USBCTRL_TYPE_DEVICEMODEL:
default:
dompath = libxl__xs_get_dompath(gc, domid);
fe_path = GCSPRINTF("%s/device/vusb/%d", dompath, ctrl);
-
be_path = vusb_be_from_xs_fe(gc, fe_path, domid);
if (!be_path) {
rc = ERROR_FAIL;